home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / net_bm.arc / SEND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-28  |  11.8 KB  |  527 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <time.h>
  4. #include <ctype.h>
  5. #if    (defined(UNIX) || defined(MICROSOFT))
  6. #include <sys/types.h>
  7. #endif
  8. #include "bm.h"
  9.  
  10. struct addr *addrecip();
  11. char *ptime();
  12.  
  13. /* send a message */
  14. dosmtpsend(mfp,toargs,nargs,subject)
  15. FILE *mfp;
  16. char *toargs[];
  17. int nargs;
  18. char *subject;
  19. {
  20.     char    smtp_subject[LINELEN], 
  21.         tstring[LINELEN];
  22.     char    *tmpnam();
  23.     FILE     *fpin;
  24.     char    *p;
  25.     char     *tf;        /* temp file name */
  26.     int    c;
  27.     int    n;
  28.     long    sequence;
  29.     struct    addr *tolist,*tp;
  30.     register FILE    *tfile;
  31.     time_t    t;
  32.  
  33.  
  34.     if (nargs == 0) {
  35.         printf("No recpients\n");
  36.         return 0;
  37.     }
  38.     fpin = mfp;
  39.     if ((tolist = make_tolist(nargs,toargs)) == NULLADDR) {
  40.         printf("Send aborted\n");
  41.         return 0;
  42.     }
  43.  
  44.     sequence = get_msgid();
  45.  
  46.     time(&t);
  47.     tf = tmpnam(NULL);
  48.         /* open textfile for write */
  49.     if ((tfile = fopen(tf,"w+")) == NULLFILE) {
  50.         perror(tf);
  51.         del_addrlist(tolist);
  52.         return 1;
  53.     }
  54.  
  55.     /* write RFC822-compatible headers using above information */
  56.     fprintf(tfile,"Date: %s",ptime(&t));
  57.     fprintf(tfile,"Message-Id: <%ld@%s>\n",sequence,hostname);
  58.     fprintf(tfile,"From: %s@%s",username,hostname);
  59.     if (fullname != NULLCHAR && *fullname != '\0')
  60.         fprintf(tfile," (%s)",fullname);
  61.     fprintf(tfile,"\n");
  62.     if (replyto != NULLCHAR && *replyto != '\0')
  63.         fprintf(tfile,"Reply-To: %s\n",replyto);
  64.     strcpy(tstring,"To: ");
  65.     for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  66.         strcat(tstring,tp->user);
  67.         if (tp->host != NULLCHAR || *tp->host != '\0') {
  68.             strcat(tstring,"@");
  69.             strcat(tstring,tp->host);
  70.         }
  71.         n = strlen(tstring);
  72.         if (tp->next) {
  73.             if (n > 50) {
  74.                 fprintf(tfile,"%s,\n\t",tstring);
  75.                 if (tty) printf("%s,\n ",tstring);
  76.                 *tstring = '\0';
  77.             } else
  78.                 strcat(tstring,", ");
  79.         }
  80.     }
  81.     fprintf(tfile,"%s\n",tstring);
  82.     if (tty) printf("%s\n",tstring); 
  83.  
  84.     *smtp_subject = '\0';
  85.     if (subject == NULL && tty) {
  86.         /* prompt and get Subject: */
  87.         printf("Subject: ");
  88.         gets(smtp_subject);
  89.     } else {
  90.         strcpy(smtp_subject,subject);
  91.         if(tty) printf("Subject: %s\n",smtp_subject);
  92.     }
  93.     fprintf(tfile,"Subject: %s\n",smtp_subject);
  94.     fprintf(tfile,"\n");       /* add empty line as separator */
  95.  
  96.     if (!tty && fpin == NULLFILE)
  97.         fpin = stdin;
  98.  
  99.     if (fpin != NULLFILE ) {
  100.         while((c = getc(fpin)) != EOF)
  101.             if(putc(c,tfile) == EOF)
  102.                 break;
  103.         if (ferror(tfile)) {
  104.             perror("tmp file");
  105.             (void) fclose(tfile);
  106.             return 1;
  107.         }
  108.     } else {
  109.         /* sending a message not from a file */
  110.         /* copy text from console to the file */
  111.         printf("\nType message text.  Enter a '.' or ctrl/D in column one to end.");
  112.         printf("\nCommands: ~p - redisplay msg, ~e - invoke editor, ~? - help\n\n");
  113.         for(;;) {
  114.             /* read line from console  ie stdin */
  115.             if (gets(tstring) == NULLCHAR)
  116.                 break;
  117.             rip(tstring);
  118.             if(strcmp(tstring,".") == 0 || tstring[0] == '\004')
  119.                 break;
  120.             if (*tstring == '~' ) {
  121.                 switch(tstring[1]) {
  122.                 case 'p':
  123.                     /* Print the message so far */
  124.                     fseek(tfile,0L,0);
  125.                     while (fgets(tstring,sizeof(tstring),tfile) != NULLCHAR)
  126.                         fputs(tstring,stdout);
  127.                     break;
  128.                 case 'e':
  129.                     /* Drop into editor */
  130.                     (void) fclose(tfile);
  131.                     if (editor == NULLCHAR) {
  132.                         printf("No editor defined\n");
  133.                         break;
  134.                     }
  135.                     sprintf(tstring,"%s %s",editor,tf);
  136.                     /* call editor to enter message text */
  137.                     if (system(tstring))
  138.                         printf("unable to invoke editor\n");
  139.                     tfile = fopen(tf,"a+");
  140.                     break;
  141.                 case 'q':
  142.                     (void) fclose(tfile);
  143.                     (void) unlink(tf);
  144.                     printf("Abort\n");
  145.                     return 0;
  146.                 case 'r': 
  147.                     {
  148.                         FILE  *infl;
  149.                         p = &tstring[2];
  150.                         while(*p == ' ' || *p == '\t')
  151.                             p++;
  152.                         if (*p == '\0')
  153.                             printf("No file name specified\n");
  154.                         else
  155.                             if((infl = fopen(p,"r")) == NULLFILE)
  156.                                 printf("No such file\n");
  157.                             else {
  158.                                 printf("Reading file %s\n",p);
  159.                                 while((c = getc(infl)) != EOF)
  160.                                     if(putc(c,tfile) == EOF)
  161.                                         break;
  162.                                 if (ferror(tfile)) {
  163.                                     perror("tmp file");
  164.                                     (void) fclose(tfile);
  165.                                     return 1;
  166.                                 }
  167.                                 (void) fclose(infl);
  168.                             }
  169.  
  170.                         break;
  171.                     }
  172.                 case 'm': 
  173.                     {
  174.                         int    msg;
  175.                         p = &tstring[2];
  176.                         while(*p == ' ' || *p == '\t')
  177.                             p++;
  178.                         if (*p == '\0')
  179.                             msg = current;
  180.                         else
  181.                             msg = atoi(p);
  182.                         if (mfile == NULLFILE || msg < 1 || msg > nmsgs)
  183.                             printf("no such message\n");
  184.                         else {
  185.                             printf("Inserting message %d\n",msg);
  186.                             msgtofile(msg,tfile,0);
  187.                         }
  188.                         break;
  189.                     }
  190.                 case '~':
  191.                     fprintf(tfile,"%s\n",&tstring[1]);
  192.                     break;
  193.                 case '?':
  194.                     printf("~e - Invoke Editor\n");
  195.                     printf("~p - Display message buffer\n");
  196.                     printf("~q - Abort this message\n");
  197.                     printf("~r file - Read file into buffer\n");
  198.                     printf("~m msg - message into buffer\n");
  199.                     printf("~~ - Enter a ~ into message\n");
  200.                     break;
  201.                 default:
  202.                     printf("Unknown ~ escape. ~? for help\n");
  203.                 }
  204.                 printf("(continue)\n");
  205.             } else
  206.                 fprintf(tfile,"%s\n",tstring);
  207.         }
  208.         printf("EOF\n");
  209.  
  210.     }
  211.     queuejob(tfile,tolist);
  212.     recordmsg(tfile,tolist->user);     /* save copy for sender */
  213.     (void) fclose(tfile);
  214.     del_addrlist(tolist);
  215.     (void) unlink(tf);
  216.     return 0;
  217. }
  218.  
  219. /* forward a message in its orginal form */
  220. bouncemsg(mfp,toargs,nargs)
  221. FILE *mfp;
  222. char *toargs[];
  223. int nargs;
  224. {
  225.     struct    addr *list;
  226.     if (nargs == 0) {
  227.         printf("No recpients\n");
  228.     } else if ((list = make_tolist(nargs,toargs)) == NULLADDR) {
  229.         printf("Bad to list\n");
  230.     } else {
  231.         queuejob(mfp,list);
  232.         del_addrlist(list);
  233.     }
  234.     return 0;
  235. }
  236.  
  237. /* Return Date/Time in Arpanet format in passed string */
  238. /* Print out the time and date field as
  239.  *        "DAY day MONTH year hh:mm:ss ZONE"
  240.  */
  241. char *
  242. ptime(t)
  243. long *t;
  244. {
  245.     register struct tm *ltm;
  246.     struct tm *localtime();
  247.     static char tz[4];
  248.     static char str[40];
  249.     extern char *getenv();
  250.     char *p;
  251.     static char *days[7] = {
  252.     "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  253.  
  254.     static char *months[12] = {
  255.         "Jan","Feb","Mar","Apr","May","Jun",
  256.         "Jul","Aug","Sep","Oct","Nov","Dec" };
  257.  
  258.     /* Read the system time */
  259.     ltm = localtime(t);
  260.  
  261.     if (*tz == '\0')
  262.         if ((p = getenv("TZ")) == NULL)
  263.             strcpy(tz,"GMT");
  264.         else
  265.             strncpy(tz,p,3);
  266.  
  267.     /* rfc 822 format */
  268.     sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
  269.         days[ltm->tm_wday],
  270.         ltm->tm_mday,
  271.         months[ltm->tm_mon],
  272.         ltm->tm_year,
  273.         ltm->tm_hour,
  274.         ltm->tm_min,
  275.         ltm->tm_sec,
  276.         tz);
  277.     return(str);
  278. }
  279.  
  280. /* save copy in the record file */
  281. recordmsg(dfile,to) 
  282. FILE *dfile;
  283. char *to;
  284. {
  285.     register int c;
  286.     FILE     *fp;
  287.     time_t    t;
  288.  
  289.     if (record == NULLCHAR)
  290.         return 1;
  291.     fseek(dfile,0L,0);
  292.     if ((fp = fopen(record,"a")) == NULLFILE) {
  293.         printf("Unable to append to %s\n",record);
  294.     } else {
  295.         (void) time(&t);
  296.         fprintf(fp,"From %s %s",to,ctime(&t));
  297.         while((c = getc(dfile)) != EOF)
  298.             if(putc(c,fp) == EOF)
  299.                 break;
  300.         if (ferror(fp)) {
  301.             (void) fclose(fp);
  302.             return 1;
  303.         }
  304.         (void) fclose(fp);
  305.     }
  306.     return 0;
  307. }
  308.  
  309. /* place a mail job in the outbound queue */
  310. int
  311. queuejob(dfile,tolist)
  312. FILE *dfile;
  313. struct addr *tolist;
  314. {
  315.     FILE *fp;
  316.     char tmpstring[50];
  317.     register struct addr *tp,*sp;
  318.     char prefix[9];
  319.     int c;
  320.     long id;
  321.  
  322.     for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  323.         if (tp->sent)
  324.             continue;
  325.         fseek(dfile,0L,0);
  326.         id = get_msgid();
  327.         sprintf(prefix,"%ld",id);
  328.         (void) mlock(mqueue,prefix);
  329.         sprintf(tmpstring,"%s/%s.txt",mqueue,prefix);
  330.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  331.             printf("unable to open %s\n",tmpstring);
  332.             (void) rmlock(mqueue,prefix);
  333.             return 1;
  334.         }
  335.         while((c = getc(dfile)) != EOF)
  336.             if(putc(c,fp) == EOF)
  337.                 break;
  338.         if (ferror(fp)) {
  339.             (void) fclose(fp);
  340.             (void) rmlock(mqueue,prefix);
  341.             return 1;
  342.         }
  343.         (void) fclose(fp);
  344.         sprintf(tmpstring,"%s/%s.wrk",mqueue,prefix);
  345.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  346.             (void) rmlock(mqueue,prefix);
  347.             return 1;
  348.         }
  349.         fprintf(fp,"%s\n%s@%s\n",tp->host,username,hostname);
  350.         fprintf(fp,"%s@%s\n",tp->user,tp->host);
  351.         tp->sent++;
  352.         /* find and other addresses to the same host */
  353.         for (sp = tp->next; sp != NULLADDR; sp = sp->next) {
  354.             if (sp->sent)
  355.                 continue;
  356.             if (strcmp(tp->host,sp->host) == 0) {
  357.                 fprintf(fp,"%s@%s\n",sp->user,sp->host);
  358.                 sp->sent++;
  359.             }
  360.         }
  361.         (void) fclose(fp);
  362.         (void) rmlock(mqueue,prefix);
  363.     }
  364.     return 0;
  365. }
  366.  
  367. #define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
  368. #define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
  369.  
  370. /* check for and alias and expand alais into a address list */
  371. struct addr *
  372. expandalias(head, user)
  373. struct addr **head;
  374. char *user;
  375. {
  376.     FILE *fp;
  377.     register char *s,*p,*h;
  378.     int inalias;
  379.     struct addr *tp;
  380.     char buf[LINELEN];
  381.     
  382.     fp = fopen(alias, "r");
  383.     
  384.         /* no alias file found */
  385.     if (fp == NULLFILE)
  386.         return addrecip(head, user, hostname);
  387.  
  388.     inalias = 0;
  389.     while (fgets(buf,LINELEN,fp) != NULLCHAR) {
  390.         p = buf;
  391.         if ( *p == '#' || *p == '\0')
  392.             continue;
  393.         rip(p);
  394.  
  395.         /* if not in an matching entry skip continuation lines */
  396.         if (!inalias && isspace(*p))
  397.             continue;
  398.  
  399.         /* when processing an active alias check for a continuation */
  400.         if (inalias) {
  401.             if (!isspace(*p)) 
  402.                 break;    /* done */
  403.         } else {
  404.             s = p;
  405.             SKIPWORD(p);
  406.             *p++ = '\0';    /* end the alias name */
  407.             if (strcmp(s,user) != 0)
  408.                 continue;    /* no match go on */
  409.             inalias = 1;
  410.         }
  411.  
  412.         /* process the recipients on the alias line */
  413.         SKIPSPACE(p);
  414.         while(*p != '\0' && *p != '#') {
  415.             s = p;
  416.             SKIPWORD(p);
  417.             if (*p != '\0')
  418.                 *p++ = '\0';
  419.             /* find hostname */
  420.             if ((h = strchr(s,'@')) != NULLCHAR)
  421.                 *h++ = '\0';
  422.             else
  423.                 h = hostname;
  424.             tp = addrecip(head,s,h);
  425.             SKIPSPACE(p);
  426.         }
  427.     }
  428.     (void) fclose(fp);
  429.  
  430.     if (inalias)    /* found and processed and alias. */
  431.         return tp;
  432.  
  433.     /* no alias found treat as a local address */
  434.     return addrecip(head, user, hostname);
  435. }
  436.  
  437. /* convert a arg list to an list of address structures */
  438. struct addr *
  439. make_tolist(argc,argv)
  440. int argc;
  441. char *argv[];
  442. {
  443.     struct addr *tolist, *tp;
  444.     char *user, *host;
  445.     int i;
  446.     tolist = NULLADDR;
  447.     for (i = 0; i < argc; i++) {
  448.         user = argv[i];
  449.         if ((host = strchr(user ,'@')) != NULLCHAR) {
  450.             *host++ = '\0';
  451.             /* if it matches our host name */
  452.             if (stricmp(host,hostname) == 0)
  453.                 host = NULLCHAR;
  454.         }
  455.  
  456.         if (host == NULLCHAR)    /* a local address */
  457.             tp = expandalias(&tolist,user);
  458.         else        /* a remote address */
  459.             tp = addrecip(&tolist, user, host);
  460.  
  461.         if (tp == NULLADDR) {
  462.             printf("Out of memory\n");
  463.             del_addrlist(tolist);
  464.             return NULLADDR;
  465.         }
  466.     }
  467.     return tolist;
  468. }
  469.  
  470. /* delete a list of mail addresses */
  471. del_addrlist(list)
  472. struct addr *list;
  473. {
  474.     struct addr *tp, *tp1;;
  475.     for (tp = list; tp != NULLADDR; tp = tp1) {
  476.         tp1 = tp->next;
  477.         if (tp->user != NULLCHAR);
  478.             free(tp->user);
  479.         if (tp->host != NULLCHAR);
  480.             free(tp->host);
  481.         (void) free((char *)tp);
  482.     }
  483. }
  484.  
  485. /* add an address to the from of the list pointed to by head 
  486. ** return NULLADDR if out of memory.
  487. */
  488. struct addr *
  489. addrecip(head,user,host)
  490. struct addr **head;
  491. char *user, *host;
  492. {
  493.     register struct addr *tp;
  494.  
  495.     tp = (struct addr *)calloc(1,sizeof(struct addr));
  496.     if (tp == NULLADDR)
  497.         return NULLADDR;
  498.  
  499.     tp->next = NULLADDR;
  500.  
  501.     /* allocate storage for the user's login */
  502.     if ((tp->user = malloc((unsigned)strlen(user)+1)) == NULLCHAR) {
  503.         (void) free((char *)tp);
  504.         return NULLADDR;
  505.     }
  506.     strcpy(tp->user,user);
  507.  
  508.     /* allocate storage for the host name */
  509.     if (host != NULLCHAR)
  510.         if ((tp->host = malloc((unsigned)strlen(host)+1)) == NULLCHAR) {
  511.             (void) free(tp->user);
  512.             (void) free((char *)tp);
  513.             return NULLADDR;
  514.         }
  515.     strcpy(tp->host,host);
  516.  
  517.     /* add entry to front of existing list */
  518.     if (*head == NULLADDR)
  519.         *head = tp;
  520.     else {
  521.         tp->next = *head;
  522.         *head = tp;
  523.     }
  524.     return tp;
  525.  
  526. }
  527.